/*
 * @Author: ls
 * @Date: 2021-11-19 16:47:44
 * @LastEditTime: 2021-11-23 11:44:34
 * @LastEditors: ls
 * @Description: 贝塞尔曲线数据
 * @FilePath: \BezierPathEditor\assets\scripts\BezierData.js
 */

let Bezier = require('Bezier');

let BezierData = (function () {
	let _this = {};

	// ------------------------【私有属性】---------------------------
	/**贝塞尔曲线关键点列表 */
	let bezierCurveLists = [];

	/**关键点 - 曲线 */
	let pointCurveDict = new Map();

	/**贝塞尔曲线数据 */
	let bezierCurveData = {
		/**运行总时长 */
		time: 2,
		/**曲线总长 */
		length: 0,
		/**曲线点列表 */
		points: [],
	};

	/**需要删除的目标节点 */
	let deleteTarget = null;

	/**曲线类型 */
	let currentBezierType = 3;
	/**每段曲线的切割份数 */
	let pointCount = 100;

	/**画板分辨率 */
	let resolution = {
		width: 720,
		height: 1280,
	};

	// ------------------------【私有方法】---------------------------

	/**
	 * 存储到曲线字典 - key:关键点,value:关联的曲线对象.(start:表示该点作为起点所在的曲线,control end类似)
	 * @param {*} curve
	 */
	let saveToPointCurveDict = function (curve) {
		let obj;
		for (const key in curve) {
			const point = curve[key];
			if (pointCurveDict.has(point)) {
				obj = pointCurveDict.get(point);
			} else {
				obj = {};
			}
			obj[key + 'Curve'] = curve;
			pointCurveDict.set(point, obj);
		}
	};

	/**
	 * 判断该点是起点,终点或者中间点
	 * @param {*} node
	 * @returns
	 */
	let getPointLocation = function (node) {
		let curveObj = pointCurveDict.get(node);
		if (curveObj) {
			if (curveObj['startCurve'] && curveObj['endCurve']) {
				return 'center';
			}
			if (curveObj['startCurve']) {
				return 'start';
			}
			if (curveObj['endCurve']) {
				return 'end';
			}
		}
		return;
	};

	/**
	 * 删除的是起点
	 * @param {*} point
	 */
	let deleteStartPoint = function (point) {
		console.warn('删除的是起点');

		if (pointCurveDict.has(point)) {
			// 找到该点关联的曲线
			let CurveObj = pointCurveDict.get(point);
			let startCurve = CurveObj.startCurve;
			CurveObj.endCurve = null;
			// 删除曲线及其相关的点
			let endCurveObj = pointCurveDict.get(startCurve.end);
			endCurveObj.endCurve = null;
			for (const key in startCurve) {
				if (key == 'end') continue;
				const _point = startCurve[key];
				pointCurveDict.delete(_point);
				_point.destroy();
			}
			deleteCurveFromBezierLists(startCurve);
		}
	};

	/**
	 * 删除中间点
	 * @param {*} point
	 */
	let deleteCenterPoint = function (point) {
		console.warn('删除的是中间点');

		if (pointCurveDict.has(point)) {
			// 中间点有前后两个曲线,删除该点就需要合并两个曲线（这里的方案是保留前面的曲线，删除后面的曲线）
			let CurveObj = pointCurveDict.get(point);
			let prevCurve = CurveObj.endCurve;
			let nextCurve = CurveObj.startCurve;
			// 把前一个曲线的终点移动到后一个曲线的终点上
			prevCurve.end = nextCurve.end;
			// 重新赋值该节点下的曲线对象的end曲线
			let prevEndCurveObj = pointCurveDict.get(prevCurve.end);
			prevEndCurveObj.endCurve = prevCurve;
			pointCurveDict.delete(point);
			// 删除后曲线相关的信息
			for (const key in nextCurve) {
				if (key == 'end') continue;
				const _point = nextCurve[key];
				pointCurveDict.delete(_point);
				_point.destroy();
			}
			// pointCurveDict.delete(nextCurve.start)
			// pointCurveDict.delete(nextCurve.control)
			// nextCurve.start.destroy();
			// nextCurve.control.destroy();
			deleteCurveFromBezierLists(nextCurve);
		}
	};

	/**
	 * 删除的是终点
	 * @param {*} point
	 */
	let deleteEndPoint = function (point) {
		console.warn('删除的是终点');
		if (pointCurveDict.has(point)) {
			let CurveObj = pointCurveDict.get(point);
			let endCurve = CurveObj.endCurve;
			CurveObj.startCurve = null;
			// 删除曲线及其相关的点
			let startCurveObj = pointCurveDict.get(endCurve.start);
			startCurveObj.startCurve = null;
			for (const key in endCurve) {
				if (key == 'start') continue;
				const _point = endCurve[key];
				pointCurveDict.delete(_point);
				_point.destroy();
			}
			// pointCurveDict.delete(endCurve.control)
			// endCurve.control.destroy();
			deleteCurveFromBezierLists(endCurve);
		}
	};

	/**
	 * 从曲线列表删除曲线
	 * @param {*} curve
	 * @returns
	 */
	let deleteCurveFromBezierLists = function (curve) {
		for (var i = 0, len = bezierCurveLists.length; i < len; i++) {
			const _curve = bezierCurveLists[i];
			if (_curve === curve) {
				bezierCurveLists.splice(i, 1);
				return;
			}
		}
	};

	// ------------------------【公有方法】---------------------------

	/**
	 * 初始化
	 * @param {*} point
	 * @param {*} control
	 * @param {*} parent
	 */
	_this.init = function () {
		this.clearAllBezier();
	};

	/**
	 * 获取分辨率
	 * @param {*} params
	 * @returns
	 */
	_this.getResolution = function (params) {
		return resolution;
	};

	/**
	 * 设置分辨率
	 * @param {*} width
	 * @param {*} height
	 * @returns
	 */
	_this.setResolution = function (width, height) {
		resolution = { width, height };
		return resolution;
	};

	/**
	 * 设置曲线切割份数
	 * @param {*} num
	 */
	_this.setPointCount = function (num) {
		pointCount = num;
	};

	/**
	 * 设置曲线类型
	 * @param {*} type
	 */
	_this.setBezierCurveType = function (type) {
		currentBezierType = type;
	};

	/**
	 * 设置删除的目标节点
	 * @param {*} node
	 */
	_this.setDeleteTarget = function (node) {
		deleteTarget = node;
	};

	/**
	 * 添加贝塞尔曲线到列表
	 * @param {*} curve
	 */
	_this.addBezierCurve = function (curve) {
		bezierCurveLists.push(curve);
	};

	/**
	 * 获取曲线类型
	 * @returns
	 */
	_this.getBezierCurveType = function () {
		return currentBezierType;
	};

	/**
	 * 获取贝塞尔曲线列表
	 * @returns
	 */
	_this.getBezierCurveLists = function () {
		return bezierCurveLists;
	};

	/**
	 * 获取贝塞尔曲线数据
	 * @returns
	 */
	_this.getBezierCurveData = function () {
		return bezierCurveData;
	};

	/**
	 * 设置贝塞尔曲线运行时长
	 * @param {*} time
	 */
	_this.setBezierCurveRunTime = function (time) {
		bezierCurveData.time = time;
	};

	/**
	 * 是否第一个曲线
	 * @returns
	 */
	_this.isFirstCurve = function () {
		return bezierCurveLists.length == 0;
	};

	/**
	 * 是否是最后一个曲线
	 * @returns
	 */
	_this.isLastCurve = function () {
		return bezierCurveLists.length <= 1;
	};

	/**
	 * 创建二阶贝塞尔曲线
	 * @param {*} pos
	 */
	_this.createTwoBezierCurve = function (pos) {
		let start, control, end;
		if (_this.isFirstCurve()) {
			if (pos.length === 3) {
				start = pos[0];
				control = pos[1];
				end = pos[2];
			}
		} else {
			start = bezierCurveLists[bezierCurveLists.length - 1].end; // 把曲线列表最后一个点作为新曲线起点
			if (pos.length === 2) {
				control = pos[0];
				end = pos[1];
			}
		}

		if (start && control && end) {
			let curve = { start, control, end };
			bezierCurveLists.push(curve);
			saveToPointCurveDict(curve);
		}
	};

	/**
	 * 创建三阶贝塞尔曲线
	 * @param {*} pos
	 */
	_this.createThreeBezierCurve = function (pos) {
		let start, control1, control2, end;
		if (_this.isFirstCurve()) {
			if (pos.length === 4) {
				start = pos[0];
				control1 = pos[1];
				control2 = pos[2];
				end = pos[3];
			}
		} else {
			start = bezierCurveLists[bezierCurveLists.length - 1].end; // 把曲线列表最后一个点作为新曲线起点
			if (pos.length === 3) {
				control1 = pos[0];
				control2 = pos[1];
				end = pos[2];
			}
		}

		if (start && control1 && control2 && end) {
			let curve = { start, control1, control2, end };
			bezierCurveLists.push(curve);
			saveToPointCurveDict(curve);
		}
	};

	/**
	 * 删除节点
	 */
	_this.deletePoint = function () {
		if (pointCurveDict.has(deleteTarget)) {
			let location = getPointLocation(deleteTarget);
			switch (location) {
				case 'start':
					deleteStartPoint(deleteTarget);
					break;
				case 'center':
					deleteCenterPoint(deleteTarget);
					break;
				case 'end':
					deleteEndPoint(deleteTarget);
					break;

				default:
					break;
			}
		}
	};

	/**
	 * 保存路径
	 */
	_this.saveBezierPath = function () {
		bezierCurveData.length = 0;
		bezierCurveData.points = [];
		for (var i = 0, len = bezierCurveLists.length; i < len; i++) {
			const bezier = bezierCurveLists[i];
			// 创建一个贝塞尔曲线
			// let bezierCurve = new Bezier(bezier.start, bezier.control, bezier.end, 100);
			// console.log("consscscds", Object.values(bezier));

			let bezierCurve = new Bezier(Object.values(bezier), 2);

			// 获取曲线点
			let points = bezierCurve.getPoints(pointCount);

			// 获取曲线长度
			let curveLength = bezierCurve.getCurveLength();
			// 计算路程长度
			bezierCurveData.length += curveLength;
			// 存储曲线点
			bezierCurveData.points.push(...points);
		}

		console.log('贝塞尔曲线关键点列表 bezierCurveLists', bezierCurveLists);
		// console.log('曲线字典 pointCurveDict->', pointCurveDict);
		// console.log('保存贝塞尔曲线(路径)数据 bezierCurveData', bezierCurveData);
	};

	/**
	 * 清理所有曲线
	 */
	_this.clearAllBezier = function () {
		bezierCurveLists = [];
		pointCurveDict.forEach((curve, point) => {
			if (point) point.destroy();
		});
		pointCurveDict.clear();
	};

	return _this;
})();

module.exports = BezierData;
